package com.hzy.oms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.hzy.enums.AftersaleStatus;
import com.hzy.enums.OrderRefundStatus;
import com.hzy.enums.OrderStatus;
import com.hzy.oms.domain.*;
import com.hzy.oms.domain.vo.AftersaleItemVo;
import com.hzy.oms.domain.vo.OrderItemVo;
import com.hzy.oms.mapper.*;
import com.hzy.utils.IDGenerator;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.hzy.oms.domain.bo.AftersaleBo;
import com.hzy.oms.domain.vo.AftersaleVo;
import com.hzy.oms.service.IAftersaleService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单售后Service业务层处理
 *
 * @author zengxin
 * @date 2023-10-18
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AftersaleServiceImpl implements IAftersaleService {

    private final AftersaleMapper baseMapper;

    private final AftersaleItemMapper aftersaleItemMapper;

    private final OrderInfoMapper orderMapper;

    private final OrderItemMapper orderItemMapper;

    private final OrderOperateHistoryMapper orderOperateHistoryMapper;

    /**
     * 查询订单售后
     */
    @Override
    public AftersaleVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询订单售后列表
     */
    @Override
    public TableDataInfo<AftersaleVo> queryPageList(AftersaleBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Aftersale> lqw = buildQueryWrapper(bo);
        Page<AftersaleVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询订单售后列表
     */
    @Override
    public List<AftersaleVo> queryList(AftersaleBo bo) {
        LambdaQueryWrapper<Aftersale> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Aftersale> buildQueryWrapper(AftersaleBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Aftersale> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getMemberId() != null, Aftersale::getMemberId, bo.getMemberId());
        lqw.eq(bo.getOrderId() != null, Aftersale::getOrderId, bo.getOrderId());
        lqw.eq(bo.getReturnAmount() != null, Aftersale::getReturnAmount, bo.getReturnAmount());
        lqw.eq(bo.getType() != null, Aftersale::getType, bo.getType());
        lqw.eq(bo.getStatus() != null, Aftersale::getStatus, bo.getStatus());
        lqw.between(params.get("beginHandleTime") != null && params.get("endHandleTime") != null,
            Aftersale::getHandleTime ,params.get("beginHandleTime"), params.get("endHandleTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getDescription()), Aftersale::getDescription, bo.getDescription());
        lqw.eq(StringUtils.isNotBlank(bo.getHandleNote()), Aftersale::getHandleNote, bo.getHandleNote());
        lqw.eq(StringUtils.isNotBlank(bo.getHandleMan()), Aftersale::getHandleMan, bo.getHandleMan());
        return lqw;
    }

    /**
     * 新增订单售后
     */
    @Override
    public Boolean insertByBo(AftersaleBo bo) {
        Aftersale add = BeanUtil.toBean(bo, Aftersale.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改订单售后
     */
    @Override
    public Boolean updateByBo(AftersaleBo bo) {
        Aftersale update = BeanUtil.toBean(bo, Aftersale.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Aftersale entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除订单售后
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional
    public String applyRefund(AftersaleBo bo) {
        OrderInfo order = orderMapper.selectById(bo.getOrderId());
        //是否符合售后条件
        this.checkIfCanApplyRefund(order);
        Date optDate = new Date();
        Long memberId = order.getMemberId();
        //创建售后单aftersale
        Aftersale addAftersale = new Aftersale();
        addAftersale.setId(IDGenerator.generateId());
        addAftersale.setMemberId(order.getMemberId());
        addAftersale.setOrderId(order.getId());
        addAftersale.setReturnAmount(order.getPayAmount());
        addAftersale.setType(bo.getType());
        addAftersale.setStatus(AftersaleStatus.APPLY.getType());
        addAftersale.setReason(bo.getReason());
        addAftersale.setQuantity(bo.getQuantity());
        addAftersale.setReason(bo.getReason());
        addAftersale.setDescription(bo.getDescription());
        addAftersale.setProofPics(bo.getProofPics());
        addAftersale.setCreateTime(optDate);
        addAftersale.setCreateBy(memberId.toString());
        addAftersale.setUpdateTime(optDate);
        addAftersale.setUpdateBy(memberId.toString());
        int rows = baseMapper.insert(addAftersale);
        if (rows != 1) {
            throw new RuntimeException("插入订单售后失败");
        }
        //创建aftersale item
        QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>();
        orderItemQw.eq("order_id", order.getId());
        List<OrderItem> orderItemList = orderItemMapper.selectList(orderItemQw);
        List<AftersaleItem> addAftersaleItemList = new ArrayList<>();
        orderItemList.forEach(orderItem -> {
            AftersaleItem aftersaleItem = new AftersaleItem();
            aftersaleItem.setMemberId(memberId);
            aftersaleItem.setAftersaleId(addAftersale.getId());
            aftersaleItem.setOrderId(orderItem.getOrderId());
            aftersaleItem.setOrderItemId(orderItem.getId());
            aftersaleItem.setReturnAmount(orderItem.getSalePrice().multiply(BigDecimal.valueOf(orderItem.getQuantity())));
            aftersaleItem.setQuantity(orderItem.getQuantity());
            aftersaleItem.setCreateTime(optDate);
            aftersaleItem.setCreateBy(memberId.toString());
            aftersaleItem.setUpdateTime(optDate);
            aftersaleItem.setUpdateBy(memberId.toString());
            addAftersaleItemList.add(aftersaleItem);
        });
        Boolean isb = aftersaleItemMapper.insertBatch(addAftersaleItemList);
        if (!isb){
            throw new RuntimeException("创建售后订单item失败");
        }
        //更新订单
        rows = orderMapper.update(null, new LambdaUpdateWrapper<OrderInfo>()
                .set(OrderInfo::getAftersaleStatus, OrderRefundStatus.APPLY.getType())
                .set(OrderInfo::getUpdateBy, memberId.toString())
                .set(OrderInfo::getUpdateTime, optDate)
                .eq(OrderInfo::getId, bo.getOrderId()));
        if (rows < 1){
            throw new RuntimeException("修改订单状态失败");
        }
        //创建订单操作记录
        OrderOperateHistory optHistory = new OrderOperateHistory();
        optHistory.setOrderId(order.getId());
        optHistory.setOrderSn(order.getOrderSn());
        optHistory.setOperateMan("" + memberId);
        optHistory.setOrderStatus(11);
        optHistory.setCreateTime(optDate);
        optHistory.setCreateBy(memberId.toString());
        optHistory.setUpdateBy(memberId.toString());
        optHistory.setUpdateTime(optDate);
        rows = orderOperateHistoryMapper.insert(optHistory);
        if (rows < 1){
            throw new RuntimeException("创建订单操作记录失败");
        }
        return "售后申请成功";
    }

    /**
     * check是否能售后 可售后的状态为：待发货、待收货、已完成
     * @param order 订单
     */
    private void checkIfCanApplyRefund(OrderInfo order){
        if (order == null){
            throw new RuntimeException("为查询到订单信息");
        }
        Integer status = order.getStatus();
        boolean flag = OrderStatus.NOT_DELIVERED.getType().equals(status) || OrderStatus.DELIVERED.getType().equals(status)
                || OrderStatus.COMPLETE.getType().equals(status);
        if (!flag){
            throw new RuntimeException("该订单无法申请售后");
        }
        if (OrderStatus.COMPLETE.getType().equals(order.getStatus()) &&
                DateUtil.betweenDay(new Date(), order.getReceiveTime(), false) > 7){
            throw new RuntimeException("订单确认收货时间已超过7天，无法申请售后");
        }
        if(OrderRefundStatus.APPLY.getType().equals(order.getAftersaleStatus())
                || OrderRefundStatus.WAIT.getType().equals(order.getAftersaleStatus())){
            throw new RuntimeException("售后正在处理中");
        }
    }

    @Transactional
    @Override
    public String cancelRefund(Long orderId, Long memberId) {
        OrderInfo order = orderMapper.selectById(orderId);
        if (order == null){
            throw new RuntimeException("未查询到该订单");
        }
        //查询是否有（待处理和退货中）售后单
        QueryWrapper<Aftersale> aftersaleQw = new QueryWrapper<>();
        aftersaleQw.eq("order_id", orderId);
        aftersaleQw.in("status", Arrays.asList(AftersaleStatus.APPLY.getType(), AftersaleStatus.WAIT.getType()));
        Aftersale aftersale = baseMapper.selectOne(aftersaleQw);
        if (aftersale == null){
            throw new RuntimeException("无售后单");
        }
        if (OrderRefundStatus.SUCCESS.getType().equals(order.getAftersaleStatus())){
            throw new RuntimeException("已退款成功");
        }
        LocalDateTime optDate = LocalDateTime.now();
        //更新售后单状态
        UpdateWrapper<Aftersale> aftersaleUpdateWrapper = new UpdateWrapper<>();
        aftersaleUpdateWrapper.eq("id", aftersale.getId());
        aftersaleUpdateWrapper.set("status", AftersaleStatus.CANCEL.getType());
        aftersaleUpdateWrapper.set("update_time", optDate);
        aftersaleUpdateWrapper.set("update_by", memberId);
        int rows = baseMapper.update(null, aftersaleUpdateWrapper);
        if (rows < 1){
            throw new RuntimeException("更新售后单失败");
        }
        //更新订单售后状态
        // 更新订单
        UpdateWrapper<OrderInfo> updateOrderWrapper = new UpdateWrapper<>();
        updateOrderWrapper.eq("id", orderId)
                .set("aftersale_status", OrderRefundStatus.NO_REFUND.getType()).set("update_time", optDate)
                .set("update_by", memberId);
        rows = orderMapper.update(null, updateOrderWrapper);
        if (rows != 1) {
            throw new RuntimeException("更新订单状态失败");
        }
        return "售后取消成功";
    }

    @Transactional
    @Override
    public AftersaleVo refundOrderDetail(Long orderId, Long memberId) {
        QueryWrapper<Aftersale> aftersaleQw = new QueryWrapper<>();
        aftersaleQw.eq("order_id", orderId);
        aftersaleQw.orderByDesc("create_time");
        aftersaleQw.last("limit 1");
        Aftersale aftersale = baseMapper.selectOne(aftersaleQw);
        if (aftersale == null){
            throw new RuntimeException("未查询到售后订单");
        }
        //查一下售后订单item
        QueryWrapper<AftersaleItem> aftersaleItemQw = new QueryWrapper<>();
        aftersaleItemQw.eq("aftersale_id", aftersale.getId());
        List<AftersaleItemVo> aftersaleItemList = aftersaleItemMapper.selectVoList(aftersaleItemQw);
        List<Long> orderItemIdList = aftersaleItemList.stream().map(AftersaleItemVo::getOrderItemId).collect(Collectors.toList());
        //再去查orderItem
        QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>();
        orderItemQw.in("id", orderItemIdList);
        AftersaleVo vo = new AftersaleVo();
        BeanUtils.copyProperties(aftersale, vo);
        vo.setAftersaleItemList(aftersaleItemList);
        vo.setOrderItemList(orderItemMapper.selectVoList(orderItemQw));
        return vo;
    }


}
